package com.heima.config;

import com.alibaba.fastjson.JSON;
import com.heima.bean.Employee;
import com.heima.common.R;
import com.heima.dao.EmployeeDao;
import com.heima.filter.MyUsernamePasswordAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    //注入dao
    @Autowired
    private EmployeeDao employeeDao;

    @Bean
    public BCryptPasswordEncoder bc(){
        return new BCryptPasswordEncoder();
    }

    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                //使用数据库查询员工信息
                return employeeDao.findByUsername(username);
            }
        });
    }

    //授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //1. 先写那种不需要登录直接访问的请求
        //2. 再写那种需要特殊角色才能访问的请求
        //3. 最后写其他的需要登录就能访问的请求
        http.authorizeRequests()
                .antMatchers("/**/*.woff", "/**/*.ttf", "/backend/page/login/login.html" , "/**/images/**", "/**/*.js", "/**/*.css", "/**/*.ico" , "/**/sendCode/**").permitAll()
                .anyRequest().authenticated()
                .and().formLogin()
                .loginPage("/backend/page/login/login.html")
                /*.successHandler((request, response, authentication)->{
                    response.setContentType("application/json;charset=utf-8");
                    response.getWriter().write("登录成功！");
                })
                .failureHandler((request,response,exception)->{
                    response.setContentType("application/json;charset=utf-8");
                    response.getWriter().write("登录失败！");
                })*/
                .and().logout().logoutUrl("/employee/logout")
                .logoutSuccessHandler((request, response, authentication)->{
                    response.setContentType("application/json;charset=utf-8");
                    response.getWriter().write(JSON.toJSONString(R.success("退出成功！")));
                })
                .and().headers().frameOptions().sameOrigin() // 设置同源策略
                .and().csrf().disable();

        // 这里要把我们写好的过滤器类对象拿到，替换springsecurity里面的账号和密码的认证过滤器类
        http.addFilterAt(mdaf(), UsernamePasswordAuthenticationFilter.class);

        //权限错误抛出的异常
        http.exceptionHandling().accessDeniedHandler((request, response, accessDeniedException)->{
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(R.error("权限不足，禁止访问！")));
        });
    }

    //设置认证管理员，需要这个方法把它暴露出来
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 配置过滤器
     * @return
     */
    @Bean
    public MyUsernamePasswordAuthenticationFilter mdaf() throws Exception {
        //构建过滤器对象
        MyUsernamePasswordAuthenticationFilter filter = new MyUsernamePasswordAuthenticationFilter();

        //2. 设置过滤器过滤的地址是什么，其实就是设置登录的地址是什么
        filter.setFilterProcessesUrl("/employee/login");

        //3. 设置认证管理员
        filter.setAuthenticationManager(authenticationManagerBean());

        //4. 认证成功之后去哪里！
        filter.setAuthenticationSuccessHandler((request, response, authentication)->{
            response.setContentType("application/json;charset=utf-8");
            Employee employee = (Employee) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            response.getWriter().write(JSON.toJSONString(R.success(employee)));
        });

        //5. 认证失败之后去哪里!
        filter.setAuthenticationFailureHandler((request,response,exception)->{
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(R.error("登录失败！11")));
        });

        return filter;
    }
}
